"""
订单管理系统

提供完整的订单生命周期管理，包括订单创建、修改、取消、执行跟踪等功能。
"""

from enum import Enum
from typing import Dict, List, Optional, Any, Callable
from datetime import datetime, timedelta
from dataclasses import dataclass, field
import asyncio
import uuid
from decimal import Decimal
import pandas as pd

from ..strategies.base_strategy import Signal, SignalType


class OrderType(Enum):
    """订单类型枚举"""
    MARKET = "market"  # 市价单
    LIMIT = "limit"  # 限价单
    STOP = "stop"  # 止损单
    STOP_LIMIT = "stop_limit"  # 止损限价单
    TWAP = "twap"  # 时间加权平均价格
    VWAP = "vwap"  # 成交量加权平均价格
    ICEBERG = "iceberg"  # 冰山单
    HIDDEN = "hidden"  # 隐藏单


class OrderStatus(Enum):
    """订单状态枚举"""
    PENDING = "pending"  # 待提交
    SUBMITTED = "submitted"  # 已提交
    PARTIAL_FILLED = "partial_filled"  # 部分成交
    FILLED = "filled"  # 完全成交
    CANCELLED = "cancelled"  # 已取消
    REJECTED = "rejected"  # 已拒绝
    EXPIRED = "expired"  # 已过期
    ERROR = "error"  # 错误状态


class OrderSide(Enum):
    """订单方向枚举"""
    BUY = "buy"  # 买入
    SELL = "sell"  # 卖出


class TimeInForce(Enum):
    """订单有效期枚举"""
    DAY = "day"  # 当日有效
    GTC = "gtc"  # 撤销前有效
    IOC = "ioc"  # 立即成交或取消
    FOK = "fok"  # 全部成交或取消


@dataclass
class OrderFill:
    """订单成交记录"""
    fill_id: str  # 成交ID
    order_id: str  # 订单ID
    symbol: str  # 标的代码
    side: OrderSide  # 交易方向
    quantity: Decimal  # 成交数量
    price: Decimal  # 成交价格
    commission: Decimal  # 手续费
    timestamp: datetime  # 成交时间
    exchange: str = ""  # 交易所
    trade_id: str = ""  # 交易ID
    metadata: Dict[str, Any] = field(default_factory=dict)


@dataclass
class Order:
    """订单数据类"""
    order_id: str  # 订单ID
    symbol: str  # 标的代码
    side: OrderSide  # 交易方向
    order_type: OrderType  # 订单类型
    quantity: Decimal  # 订单数量
    price: Optional[Decimal] = None  # 订单价格
    stop_price: Optional[Decimal] = None  # 止损价格
    time_in_force: TimeInForce = TimeInForce.DAY  # 有效期
    status: OrderStatus = OrderStatus.PENDING  # 订单状态
    
    # 执行信息
    filled_quantity: Decimal = Decimal('0')  # 已成交数量
    remaining_quantity: Optional[Decimal] = None  # 剩余数量
    avg_fill_price: Optional[Decimal] = None  # 平均成交价格
    total_commission: Decimal = Decimal('0')  # 总手续费
    
    # 时间信息
    created_at: datetime = field(default_factory=datetime.now)
    submitted_at: Optional[datetime] = None
    updated_at: datetime = field(default_factory=datetime.now)
    expires_at: Optional[datetime] = None
    
    # 策略信息
    strategy_id: Optional[str] = None  # 策略ID
    signal_id: Optional[str] = None  # 信号ID
    parent_order_id: Optional[str] = None  # 父订单ID
    
    # 执行参数
    execution_params: Dict[str, Any] = field(default_factory=dict)
    
    # 成交记录
    fills: List[OrderFill] = field(default_factory=list)
    
    # 元数据
    metadata: Dict[str, Any] = field(default_factory=dict)
    
    def __post_init__(self):
        """初始化后处理"""
        if self.remaining_quantity is None:
            self.remaining_quantity = self.quantity
    
    @property
    def is_active(self) -> bool:
        """订单是否活跃"""
        return self.status in [OrderStatus.PENDING, OrderStatus.SUBMITTED, OrderStatus.PARTIAL_FILLED]
    
    @property
    def is_filled(self) -> bool:
        """订单是否完全成交"""
        return self.status == OrderStatus.FILLED
    
    @property
    def is_cancelled(self) -> bool:
        """订单是否已取消"""
        return self.status == OrderStatus.CANCELLED
    
    @property
    def fill_ratio(self) -> float:
        """成交比例"""
        if self.quantity == 0:
            return 0.0
        return float(self.filled_quantity / self.quantity)
    
    def add_fill(self, fill: OrderFill) -> None:
        """添加成交记录"""
        self.fills.append(fill)
        self.filled_quantity += fill.quantity
        self.total_commission += fill.commission
        self.remaining_quantity = self.quantity - self.filled_quantity
        
        # 更新平均成交价格
        if self.filled_quantity > 0:
            total_value = sum(fill.quantity * fill.price for fill in self.fills)
            self.avg_fill_price = total_value / self.filled_quantity
        
        # 更新订单状态
        if self.remaining_quantity <= 0:
            self.status = OrderStatus.FILLED
        elif self.filled_quantity > 0:
            self.status = OrderStatus.PARTIAL_FILLED
        
        self.updated_at = datetime.now()
    
    def to_dict(self) -> Dict[str, Any]:
        """转换为字典"""
        return {
            "order_id": self.order_id,
            "symbol": self.symbol,
            "side": self.side.value,
            "order_type": self.order_type.value,
            "quantity": float(self.quantity),
            "price": float(self.price) if self.price else None,
            "stop_price": float(self.stop_price) if self.stop_price else None,
            "time_in_force": self.time_in_force.value,
            "status": self.status.value,
            "filled_quantity": float(self.filled_quantity),
            "remaining_quantity": float(self.remaining_quantity) if self.remaining_quantity else None,
            "avg_fill_price": float(self.avg_fill_price) if self.avg_fill_price else None,
            "total_commission": float(self.total_commission),
            "created_at": self.created_at.isoformat(),
            "submitted_at": self.submitted_at.isoformat() if self.submitted_at else None,
            "updated_at": self.updated_at.isoformat(),
            "expires_at": self.expires_at.isoformat() if self.expires_at else None,
            "strategy_id": self.strategy_id,
            "signal_id": self.signal_id,
            "parent_order_id": self.parent_order_id,
            "execution_params": self.execution_params,
            "fills": [
                {
                    "fill_id": fill.fill_id,
                    "quantity": float(fill.quantity),
                    "price": float(fill.price),
                    "commission": float(fill.commission),
                    "timestamp": fill.timestamp.isoformat(),
                    "exchange": fill.exchange,
                    "trade_id": fill.trade_id
                }
                for fill in self.fills
            ],
            "metadata": self.metadata
        }


class OrderManager:
    """
    订单管理器
    
    负责订单的创建、修改、取消、状态跟踪等功能。
    """
    
    def __init__(self):
        """初始化订单管理器"""
        self._orders: Dict[str, Order] = {}
        self._active_orders: Dict[str, Order] = {}
        self._order_history: List[Order] = []
        self._callbacks: Dict[str, List[Callable]] = {
            "order_created": [],
            "order_submitted": [],
            "order_filled": [],
            "order_cancelled": [],
            "order_rejected": [],
            "order_updated": []
        }
        self._lock = asyncio.Lock()
    
    async def create_order(
        self,
        symbol: str,
        side: OrderSide,
        order_type: OrderType,
        quantity: Decimal,
        price: Optional[Decimal] = None,
        stop_price: Optional[Decimal] = None,
        time_in_force: TimeInForce = TimeInForce.DAY,
        strategy_id: Optional[str] = None,
        signal_id: Optional[str] = None,
        execution_params: Optional[Dict[str, Any]] = None,
        metadata: Optional[Dict[str, Any]] = None
    ) -> Order:
        """
        创建订单
        
        Args:
            symbol: 标的代码
            side: 交易方向
            order_type: 订单类型
            quantity: 订单数量
            price: 订单价格
            stop_price: 止损价格
            time_in_force: 有效期
            strategy_id: 策略ID
            signal_id: 信号ID
            execution_params: 执行参数
            metadata: 元数据
            
        Returns:
            创建的订单
        """
        async with self._lock:
            # 生成订单ID
            order_id = str(uuid.uuid4())
            
            # 创建订单
            order = Order(
                order_id=order_id,
                symbol=symbol,
                side=side,
                order_type=order_type,
                quantity=quantity,
                price=price,
                stop_price=stop_price,
                time_in_force=time_in_force,
                strategy_id=strategy_id,
                signal_id=signal_id,
                execution_params=execution_params or {},
                metadata=metadata or {}
            )
            
            # 设置过期时间
            if time_in_force == TimeInForce.DAY:
                # 当日有效，设置为当日收盘时间
                order.expires_at = datetime.now().replace(hour=15, minute=0, second=0, microsecond=0)
                if order.expires_at <= datetime.now():
                    order.expires_at += timedelta(days=1)
            
            # 存储订单
            self._orders[order_id] = order
            self._active_orders[order_id] = order
            
            # 触发回调
            await self._trigger_callbacks("order_created", order)
            
            return order
    
    async def create_order_from_signal(
        self,
        signal: Signal,
        quantity: Decimal,
        order_type: OrderType = OrderType.MARKET,
        strategy_id: Optional[str] = None,
        execution_params: Optional[Dict[str, Any]] = None
    ) -> Order:
        """
        根据交易信号创建订单
        
        Args:
            signal: 交易信号
            quantity: 订单数量
            order_type: 订单类型
            strategy_id: 策略ID
            execution_params: 执行参数
            
        Returns:
            创建的订单
        """
        # 确定交易方向
        side = OrderSide.BUY if signal.signal_type in [SignalType.BUY] else OrderSide.SELL
        
        # 确定价格
        price = None
        stop_price = None
        
        if order_type == OrderType.LIMIT:
            price = Decimal(str(signal.price)) if signal.price else None
        elif order_type == OrderType.STOP:
            stop_price = Decimal(str(signal.stop_loss)) if signal.stop_loss else None
        elif order_type == OrderType.STOP_LIMIT:
            price = Decimal(str(signal.take_profit)) if signal.take_profit else None
            stop_price = Decimal(str(signal.stop_loss)) if signal.stop_loss else None
        
        return await self.create_order(
            symbol=signal.symbol,
            side=side,
            order_type=order_type,
            quantity=quantity,
            price=price,
            stop_price=stop_price,
            strategy_id=strategy_id,
            signal_id=str(id(signal)),
            execution_params=execution_params,
            metadata={
                "signal_strength": signal.strength,
                "signal_confidence": signal.confidence,
                "signal_timestamp": signal.timestamp.isoformat()
            }
        )
    
    async def submit_order(self, order_id: str) -> bool:
        """
        提交订单
        
        Args:
            order_id: 订单ID
            
        Returns:
            提交是否成功
        """
        async with self._lock:
            order = self._orders.get(order_id)
            if not order:
                return False
            
            if order.status != OrderStatus.PENDING:
                return False
            
            # 更新订单状态
            order.status = OrderStatus.SUBMITTED
            order.submitted_at = datetime.now()
            order.updated_at = datetime.now()
            
            # 触发回调
            await self._trigger_callbacks("order_submitted", order)
            
            return True
    
    async def cancel_order(self, order_id: str, reason: str = "") -> bool:
        """
        取消订单
        
        Args:
            order_id: 订单ID
            reason: 取消原因
            
        Returns:
            取消是否成功
        """
        async with self._lock:
            order = self._orders.get(order_id)
            if not order:
                return False
            
            if not order.is_active:
                return False
            
            # 更新订单状态
            order.status = OrderStatus.CANCELLED
            order.updated_at = datetime.now()
            order.metadata["cancel_reason"] = reason
            
            # 从活跃订单中移除
            self._active_orders.pop(order_id, None)
            
            # 添加到历史记录
            self._order_history.append(order)
            
            # 触发回调
            await self._trigger_callbacks("order_cancelled", order)
            
            return True
    
    async def modify_order(
        self,
        order_id: str,
        quantity: Optional[Decimal] = None,
        price: Optional[Decimal] = None,
        stop_price: Optional[Decimal] = None
    ) -> bool:
        """
        修改订单
        
        Args:
            order_id: 订单ID
            quantity: 新数量
            price: 新价格
            stop_price: 新止损价格
            
        Returns:
            修改是否成功
        """
        async with self._lock:
            order = self._orders.get(order_id)
            if not order:
                return False
            
            if not order.is_active:
                return False
            
            # 修改订单参数
            if quantity is not None:
                order.quantity = quantity
                order.remaining_quantity = quantity - order.filled_quantity
            
            if price is not None:
                order.price = price
            
            if stop_price is not None:
                order.stop_price = stop_price
            
            order.updated_at = datetime.now()
            
            # 触发回调
            await self._trigger_callbacks("order_updated", order)
            
            return True
    
    async def fill_order(
        self,
        order_id: str,
        quantity: Decimal,
        price: Decimal,
        commission: Decimal = Decimal('0'),
        exchange: str = "",
        trade_id: str = ""
    ) -> bool:
        """
        订单成交
        
        Args:
            order_id: 订单ID
            quantity: 成交数量
            price: 成交价格
            commission: 手续费
            exchange: 交易所
            trade_id: 交易ID
            
        Returns:
            成交处理是否成功
        """
        async with self._lock:
            order = self._orders.get(order_id)
            if not order:
                return False
            
            if not order.is_active:
                return False
            
            # 创建成交记录
            fill = OrderFill(
                fill_id=str(uuid.uuid4()),
                order_id=order_id,
                symbol=order.symbol,
                side=order.side,
                quantity=quantity,
                price=price,
                commission=commission,
                timestamp=datetime.now(),
                exchange=exchange,
                trade_id=trade_id
            )
            
            # 添加成交记录
            order.add_fill(fill)
            
            # 如果订单完全成交，从活跃订单中移除
            if order.is_filled:
                self._active_orders.pop(order_id, None)
                self._order_history.append(order)
            
            # 触发回调
            await self._trigger_callbacks("order_filled", order)
            
            return True
    
    async def reject_order(self, order_id: str, reason: str = "") -> bool:
        """
        拒绝订单
        
        Args:
            order_id: 订单ID
            reason: 拒绝原因
            
        Returns:
            拒绝处理是否成功
        """
        async with self._lock:
            order = self._orders.get(order_id)
            if not order:
                return False
            
            # 更新订单状态
            order.status = OrderStatus.REJECTED
            order.updated_at = datetime.now()
            order.metadata["reject_reason"] = reason
            
            # 从活跃订单中移除
            self._active_orders.pop(order_id, None)
            
            # 添加到历史记录
            self._order_history.append(order)
            
            # 触发回调
            await self._trigger_callbacks("order_rejected", order)
            
            return True
    
    async def expire_orders(self) -> List[str]:
        """
        处理过期订单
        
        Returns:
            过期订单ID列表
        """
        expired_orders = []
        current_time = datetime.now()
        
        async with self._lock:
            for order_id, order in list(self._active_orders.items()):
                if order.expires_at and current_time >= order.expires_at:
                    order.status = OrderStatus.EXPIRED
                    order.updated_at = current_time
                    
                    self._active_orders.pop(order_id)
                    self._order_history.append(order)
                    
                    expired_orders.append(order_id)
        
        return expired_orders
    
    def get_order(self, order_id: str) -> Optional[Order]:
        """获取订单"""
        return self._orders.get(order_id)
    
    def get_active_orders(self, symbol: Optional[str] = None) -> List[Order]:
        """获取活跃订单"""
        orders = list(self._active_orders.values())
        if symbol:
            orders = [order for order in orders if order.symbol == symbol]
        return orders
    
    def get_order_history(
        self,
        symbol: Optional[str] = None,
        start_date: Optional[datetime] = None,
        end_date: Optional[datetime] = None,
        limit: Optional[int] = None
    ) -> List[Order]:
        """获取订单历史"""
        orders = self._order_history.copy()
        
        # 按符号筛选
        if symbol:
            orders = [order for order in orders if order.symbol == symbol]
        
        # 按时间筛选
        if start_date:
            orders = [order for order in orders if order.created_at >= start_date]
        if end_date:
            orders = [order for order in orders if order.created_at <= end_date]
        
        # 按时间排序
        orders.sort(key=lambda x: x.created_at, reverse=True)
        
        # 限制数量
        if limit:
            orders = orders[:limit]
        
        return orders
    
    def get_orders_by_strategy(self, strategy_id: str) -> List[Order]:
        """获取策略相关订单"""
        return [order for order in self._orders.values() if order.strategy_id == strategy_id]
    
    def get_order_statistics(self) -> Dict[str, Any]:
        """获取订单统计信息"""
        all_orders = list(self._orders.values())
        active_orders = list(self._active_orders.values())
        
        # 按状态统计
        status_counts = {}
        for status in OrderStatus:
            status_counts[status.value] = len([o for o in all_orders if o.status == status])
        
        # 按类型统计
        type_counts = {}
        for order_type in OrderType:
            type_counts[order_type.value] = len([o for o in all_orders if o.order_type == order_type])
        
        # 成交统计
        filled_orders = [o for o in all_orders if o.is_filled]
        total_volume = sum(float(o.quantity) for o in filled_orders)
        total_value = sum(float(o.quantity * o.avg_fill_price) for o in filled_orders if o.avg_fill_price)
        total_commission = sum(float(o.total_commission) for o in all_orders)
        
        return {
            "total_orders": len(all_orders),
            "active_orders": len(active_orders),
            "status_distribution": status_counts,
            "type_distribution": type_counts,
            "execution_statistics": {
                "filled_orders": len(filled_orders),
                "total_volume": total_volume,
                "total_value": total_value,
                "total_commission": total_commission,
                "avg_fill_ratio": sum(o.fill_ratio for o in all_orders) / len(all_orders) if all_orders else 0
            }
        }
    
    async def register_callback(self, event: str, callback: Callable) -> None:
        """注册回调函数"""
        if event in self._callbacks:
            self._callbacks[event].append(callback)
    
    async def _trigger_callbacks(self, event: str, order: Order) -> None:
        """触发回调函数"""
        if event in self._callbacks:
            for callback in self._callbacks[event]:
                try:
                    if asyncio.iscoroutinefunction(callback):
                        await callback(order)
                    else:
                        callback(order)
                except Exception as e:
                    print(f"Error in callback {callback}: {e}")
    
    async def cleanup(self) -> None:
        """清理资源"""
        # 取消所有活跃订单
        for order_id in list(self._active_orders.keys()):
            await self.cancel_order(order_id, "System cleanup")
        
        # 清空回调
        for callbacks in self._callbacks.values():
            callbacks.clear()